package service

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"net/http"
	"smart-sensor-cloud/internal/model"
	"smart-sensor-cloud/pkg/auth"
	"smart-sensor-cloud/pkg/util"
	"strconv"
)

func GetRoleSelections(ctx *gin.Context) {
	roles, err := model.GetAllRoles()
	if err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: "查询角色选择列表失败",
		})
		return
	}

	util.ResponseOK(ctx, util.OKWithPayload(roles))
}

func GetRoleWithID(ctx *gin.Context) {
	roleIDStr := ctx.Param("id")
	if roleIDStr == "" {
		ctx.Set("error", util.NewInvalidParameterError("角色ID不可以为空"))
		return
	}

	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("非法的参数"))
		return
	}

	role, err := model.GetRoleWithID(roleID)
	if err != nil {
		ctx.Set("error", util.NewResourceNotFoundError(err.Error()))
		return
	}

	util.ResponseOK(ctx, util.OKWithPayload(role))
}

func GetRolesWithParentID(ctx *gin.Context) {
	roleIDStr := ctx.Param("id")
	if roleIDStr == "" {
		ctx.Set("error", util.NewInvalidParameterError("角色ID不可以为空"))
		return
	}

	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("非法的参数"))
		return
	}

	children, err := model.GetChildrenWithParentID(roleID)
	if err != nil {
		ctx.Set("error", util.NewResourceNotFoundError(err.Error()))
		return
	}

	util.ResponseOK(ctx, util.OKWithPayload(children))
}

func GetRoles(ctx *gin.Context) {
	sizeStr := ctx.DefaultQuery("size", "10")
	indexStr := ctx.DefaultQuery("page", "1")

	size, err := strconv.Atoi(sizeStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("参数转换失败"))
		return
	}
	index, err := strconv.Atoi(indexStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("参数转换失败"))
		return
	}

	if results, total, err := model.GetRoles(index, size); err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: "查询角色列表失败",
		})
		return
	} else {
		util.ResponseOK(ctx, util.OKWithPayload(&util.PaginationResp{
			Size:  size,
			Index: index,
			Data:  results,
			Total: total,
		}))
	}
}

func AddRole(ctx *gin.Context) {
	role := new(model.Role)

	if err := ctx.MustBindWith(role, binding.JSON); err != nil {
		ctx.Set("error", util.NewInvalidParameterError(err.Error()))
		return
	}

	if err := model.AddRole(role); err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		})
		return
	}

	auth.LoadCasbinPolicy(ctx)
	util.ResponseOK(ctx, util.OK())
}

func DeleteRole(ctx *gin.Context) {
	roleIDStr := ctx.Query("id")

	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("参数转换失败"))
		return
	}

	if err := model.DeleteRole(roleID); err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		})
		return
	}

	auth.LoadCasbinPolicy(ctx)
	util.ResponseOK(ctx, util.OK())
}

func UpdateRole(ctx *gin.Context) {
	roleIDStr := ctx.Query("id")

	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("参数转换失败"))
		return
	}

	change := new(model.Role)
	if err := ctx.MustBindWith(change, binding.JSON); err != nil {
		ctx.Set("error", util.NewInvalidParameterError(err.Error()))
		return
	}

	if err := model.UpdateRole(roleID, change); err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		})
		return
	}

	auth.LoadCasbinPolicy(ctx)
	util.ResponseOK(ctx, util.OK())
}

func UpdateRoleMenuWithRoleID(ctx *gin.Context) {
	roleIDStr := ctx.Param("id")

	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		ctx.Set("error", util.NewInvalidParameterError("参数转换失败"))
		return
	}

	change := new(model.Menus)
	if err := ctx.MustBindWith(change, binding.JSON); err != nil {
		ctx.Set("error", util.NewInvalidParameterError(err.Error()))
		return
	}

	if err := model.UpdateRoleMenus(roleID, change); err != nil {
		ctx.Set("error", &util.Error{
			Code:    http.StatusInternalServerError,
			Message: err.Error(),
		})
		return
	}

	auth.LoadCasbinPolicy(ctx)
	util.ResponseOK(ctx, util.OK())
}
